package com.ruoyi.websocket.handler;

import cn.hutool.extra.spring.SpringUtil;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.websocket.config.INettyConfig;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.AttributeKey;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.StandardCharsets;
import java.util.Map;

@Slf4j
public class HttpRequestHandler extends SimpleChannelInboundHandler<FullHttpRequest> {
    private INettyConfig iNettyConfig;
    public HttpRequestHandler() {
        iNettyConfig = SpringUtil.getBean(INettyConfig.class);
    }

    public HttpRequestHandler(INettyConfig iNettyConfig) {
        this.iNettyConfig = iNettyConfig;
    }
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {

    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, FullHttpRequest request) {
        // 1. 判断是否为WebSocket升级请求
        if (isWebSocketUpgrade(request)) {
            try {
                // 2. 在这里获取所有请求信息！
                String uri = request.uri(); // 获取完整URI，例如：/ws?token=abc123
                //获取所有问号参数
                Map<String, String> params = cn.hutool.http.HttpUtil.decodeParamMap(uri, StandardCharsets.UTF_8);
                HttpHeaders headers = request.headers();
                int endIndex = uri.indexOf("?");
                if (endIndex != -1) {
                    uri = uri.substring(0, endIndex);
                }
                //把集合保存起来,这里可以解决随便上送路径导致一起连接的问题
                if (!uri.equals(iNettyConfig.getWebsocketPath())) {
                    log.info("连接路径错误");
                    // 校验失败：返回HTTP 403错误
                    sendErrorResponse(ctx, request, HttpResponseStatus.FORBIDDEN, "连接路径错误");
                    return;
                }
                if (iNettyConfig.getEnabledToken()) {
                    String token = StringUtils.isNotEmpty(params.get(iNettyConfig.getUserFlag())) ? params.get(iNettyConfig.getUserFlag()) : headers.get(iNettyConfig.getUserFlag());
                    if (StringUtils.isEmpty(token)) {
                        sendErrorResponse(ctx, request, HttpResponseStatus.FORBIDDEN, "token不能为空");
                        return;
                    }
                    ctx.channel().attr(AttributeKey.valueOf("TOKEN")).set(token);
                    IMessageProcessor.allChannel.put(token, ctx);
                }else{
                    IMessageProcessor.allChannel.put(ctx.channel().id().asLongText(), ctx);
                }
                request.setUri(uri);

                String clientIp = ctx.channel().remoteAddress().toString(); // 获取客户端IP
                HttpMethod method = request.method(); // 获取请求方法（应该是GET）

                // 3. (关键步骤) 将信息存储到Channel的属性中，供后续处理器使用
                ctx.channel().attr(AttributeKey.valueOf("HTTP_PARAMS")).set(params);
                ctx.channel().attr(AttributeKey.valueOf("HTTP_HEADERS")).set(headers);

                // 4. 保留引用，以便后续的WebSocketProtocolHandler继续处理握手
                ctx.fireChannelRead(request.retain());

                // 5. 从pipeline中移除自己，因为后续通信都是WebSocket帧，不再是HTTP请求
                ctx.pipeline().remove(this);

            } catch (Exception e) {
                log.error("连接错误:{}",e);
                sendErrorResponse(ctx, request, HttpResponseStatus.INTERNAL_SERVER_ERROR, "系统异常");
            }

        } else {
            // 处理普通HTTP请求
//            sendHttpResponse(ctx, request, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.FORBIDDEN));
            log.info("不支持处理http请求");
            sendErrorResponse(ctx, request, HttpResponseStatus.FORBIDDEN, "不支持处理http请求");
        }
    }
    /**
     * 发送HTTP错误响应
     */
    private void sendErrorResponse(ChannelHandlerContext ctx, FullHttpRequest request,
                                   HttpResponseStatus status, String errorMessage) {
        FullHttpResponse response = new DefaultFullHttpResponse(
                HttpVersion.HTTP_1_1,
                status,
                Unpooled.copiedBuffer("{\"error\": \"" + errorMessage + "\"}", StandardCharsets.UTF_8)
        );

        response.headers().set(HttpHeaderNames.CONTENT_TYPE, "application/json; charset=UTF-8");
        response.headers().set(HttpHeaderNames.CONTENT_LENGTH, response.content().readableBytes());

        // 如果是Keep-Alive连接，设置对应的header
        if (HttpUtil.isKeepAlive(request)) {
            response.headers().set(HttpHeaderNames.CONNECTION, HttpHeaderValues.KEEP_ALIVE);
        }

        ctx.writeAndFlush(response).addListener(ChannelFutureListener.CLOSE);
    }
    private boolean isWebSocketUpgrade(FullHttpRequest request) {
        return request.headers().contains(HttpHeaderNames.UPGRADE) &&
                request.headers().contains(HttpHeaderNames.CONNECTION, HttpHeaderValues.UPGRADE, true) &&
                request.headers().contains(HttpHeaderNames.SEC_WEBSOCKET_KEY);
    }

    private void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest request, FullHttpResponse response) {
        // ... 发送HTTP响应的实现 ...
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx)  {
        //只负责建立连接，连接建立后，会马上走这个方法
        log.info("断开成功：handlerRemoved");
    }
}
